package camid.services.cloudmanager;

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


public class CloudManagerAgent implements Runnable 
{

	private ClusterManager cloudManager;
	private AtomicInteger buffer;
	private long interval;
	
	private static final Logger logger = LogManager.getLogger(CloudManagerAgent.class.getName());
	
	public CloudManagerAgent(ClusterManager cloudManager, long balancingInterval)
	{
		this.cloudManager = cloudManager;
		this.interval = balancingInterval;
		this.buffer = new AtomicInteger(1);
	}
	
	@Override
	public void run() {
		while(buffer.get() != 0)
		{	
			try 
			{	
				this.cloudManager.updateCostMap();
				Map<String,Double> costMap = this.cloudManager.getCostMap();
				logger.info( "Cost Map: " + costMap.toString());
				String leastNodeId = null;
				Double leastCost = Double.MAX_VALUE;
				
				String maxNodeId = null;
				Double maxCost = 0.0;
				
				synchronized( costMap )
				{
					for(Entry<String,Double> entry : costMap.entrySet())
					{
						Double cost = entry.getValue();
						if( cost < leastCost )
						{
							leastNodeId = entry.getKey();
							leastCost = entry.getValue();
						}
						
						if( cost >= maxCost )
						{
							maxNodeId = entry.getKey();
							maxCost = entry.getValue();
						}
					}
				}
				
				logger.info( "Least cost node: " + leastNodeId + "=> " + leastCost);
				logger.info( "Max cost node: " + maxNodeId + "=> " + maxCost);
				
				if(leastNodeId != null && maxNodeId != null && !leastNodeId.equals(maxNodeId))
				{
					logger.info("Balancing " + leastNodeId + " and " + maxNodeId);
					this.cloudManager.balanceNodes(maxNodeId, leastNodeId);
				}
				
				Thread.sleep(interval);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
			
			
		}
		
	}
	
	public void stop()
	{
		buffer.set(0);
	}
	
}
